package com.ssl;


import com.baosight.demo.trust.MyX509TrustManager;

import java.io.*;
import java.net.URL;
import java.security.KeyStore;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;

public class HttpsCaller {
    public static void main(String[] args) {
        try {
            /*
             * 请求有权威证书的地址
             */
            String requestPath = "https://www.baidu.com/";
            HttpsURLConnection connection = null;//getHttpsURLConnection(requestPath, "GET");
            String result = "";//new String(getBytesFromInputStream(connection.getInputStream()));
            System.out.println("GET1返回结果：" + result);

            /*
             * 请求自定义证书的地址
             */
            //获取信任库
            //KeyStore trustStore = getkeyStore("jks", "d:/temp/cacerts", "123456");

//            //不需客户端证书
//            requestPath = "https://x.x.x.x:9010/zsywservice";
//            connection = getHttpsURLConnection(requestPath, "GET", null, null, trustStore);
//            result = new String(getBytesFromInputStream(connection.getInputStream()));
//            System.out.println("GET2返回结果：" + result);

            //需客户端证书
            requestPath = "https://10.25.25.129:8080/ice/xCyber/Demo/callMiddle";
            KeyStore keyStore = getkeyStore("pkcs12", "c:\\keystore\\testSSL\\client.p12", "clientpass");
            connection = getHttpsURLConnection(requestPath, "POST", keyStore, "clientpass", null);
            connection.setRequestProperty("Content-Type","application/json");
            OutputStream os = connection.getOutputStream();
            OutputStreamWriter osw = new OutputStreamWriter(os, "UTF-8");
            osw.write("{\"paramList\":[123456]}");
            osw.flush();
            System.out.println(connection.getResponseCode());
            System.out.println(connection.getResponseMessage());
            System.out.println("~~~~~~~~~");
            result = new String(getBytesFromInputStream(connection.getInputStream()));
            System.out.println("GET3返回结果：" + result);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 获取证书
     * @return
     */
    private static KeyStore getkeyStore(String type, String filePath, String password) {
        KeyStore keySotre = null;
        FileInputStream in = null;
        try {
            keySotre = KeyStore.getInstance(type);
            in = new FileInputStream(new File(filePath));
            keySotre.load(in, password.toCharArray());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            FileUtil.close(in);
        }
        return keySotre;
    }

    private static HttpsURLConnection getHttpsURLConnection(String uri, String method) throws Exception {
        URL url = new URL(uri);
        HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
        connection.setRequestMethod(method);
        connection.setDoInput(true);
        connection.setDoOutput(true);
        return connection;
    }

    /**
     * 获取连接
     * @param uri
     * @param method
     * @param keyStore
     * @param trustStore
     * @return
     * @throws Exception
     */
    private static HttpsURLConnection getHttpsURLConnection(String uri, String method, KeyStore keyStore, String keyStorePassword, KeyStore trustStore) throws Exception {
        KeyManager[] keyManagers = null;
        TrustManager[] trustManagers = null;
        if (keyStore != null) {
            KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
            keyManagerFactory.init(keyStore, keyStorePassword.toCharArray());
            keyManagers = keyManagerFactory.getKeyManagers();
        }
        if (trustStore != null) {
            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("SunX509");
            trustManagerFactory.init(trustStore);
            trustManagers = trustManagerFactory.getTrustManagers();
        } else {
            trustManagers = new TrustManager[] { new DefaultTrustManager()};
        }

        //设置服务端支持的协议
        SSLContext context = SSLContext.getInstance("TLSv1.2");
        context.init(keyManagers, trustManagers, null);
        SSLSocketFactory sslFactory = context.getSocketFactory();

        URL url = new URL(uri);
        HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
        connection.setSSLSocketFactory(sslFactory);
        //验证URL的主机名和服务器的标识主机名是否匹配
        connection.setHostnameVerifier(new HostnameVerifier() {
            @Override
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        });
        connection.setRequestMethod(method);
        connection.setDoInput(true);
        connection.setDoOutput(true);
        return connection;
    }

    /**
     * 默认的TrustManager实现，不安全
     */
    private static final class DefaultTrustManager implements X509TrustManager {
        @Override
        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        }

        @Override
        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        }

        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return null;
        }
    }

    /**
     * 从输入流获取数据
     * @param in
     * @return
     * @throws IOException
     */
    private static byte[] getBytesFromInputStream(InputStream in) throws IOException {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        byte[] b = new byte[1024];
        int len;
        while ((len = in.read(b)) != -1) {
            out.write(b, 0, len);
        }
        byte[] bytes = out.toByteArray();
        out.close();
        return bytes;
    }
}
class FileUtil{
    public static void close(InputStream in){
        try {
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}